package com.wenbo.transfor;

import com.wenbo.utils.Threads;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.*;
import java.net.ConnectException;
import java.net.InetAddress;
import java.net.Socket;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.ThreadPoolExecutor;


public class SendFileThread {
	//private Logger logger = LoggerFactory.getLogger(SendFileThread.class);

	private Socket socket;
	private JFrame frame;
	private JLabel label;
	private JProgressBar progressbar;
	private String path = null;
	private JButton cancel;
	private JButton start;

	private JTextField time;

	private int counter;
	private Timer timer;
	private final Object lock;
	private boolean resume = true;
	private final Object lock2;

	private String ip;


	private long offset;
	private int barOffset = 0;



	private ThreadPoolExecutor threadPoolExecutor;



	public SendFileThread(Object lock,Object lock2,String ip){
		this.lock = lock;
		this.lock2 = lock2;
		this.ip = ip;
	}

	private void createSocket(String ip){
		try {
			socket = new Socket(ip, 10052);
		} catch (IOException e) {
			if (e instanceof ConnectException) {
				JOptionPane.showMessageDialog(frame, "找不到接收方!", "提示", JOptionPane.WARNING_MESSAGE);
			}
			frame.dispose();
			System.exit(0);
		}
	}
	public void startSend() {
		threadPoolExecutor = Threads.threadPoolExecutor();
		frame = new JFrame("文件传输");
		createSocket(ip);
		frame.setSize(479, 412);
		//frame.setLocation(439,228);
		frame.setLayout(null);
		Container container = frame.getContentPane();
		JLabel titleLabel = new JLabel("文件发送端",null,SwingConstants.LEFT);
		titleLabel.setFont(new Font("华文行楷",Font.BOLD,22));
		titleLabel.setBounds(140,0,200,30);
		container.add(titleLabel);
		time = new JTextField("0");
		time.setEditable(false);
		time.setBounds(300,0,50,30);
		int minute = counter / 60;
		int second = counter % 60;
		time.setText("耗时:"+minute+"分"+second+"秒");
        time.setSelectedTextColor(Color.BLUE);
		time.setBounds(350,0,100,30);
		time.setForeground(Color.RED);
		container.add(time);
		label = new JLabel("准备发送");
		label.setBounds(50,30,400,30);
		container.add(label);
		progressbar = new JProgressBar();//进度条
		progressbar.setBounds(50,65,230,25);
		progressbar.setOrientation(JProgressBar.HORIZONTAL);
		progressbar.setMinimum(0);
		progressbar.setStringPainted(true);
		progressbar.setPreferredSize(new Dimension(150, 20));
		progressbar.setBorderPainted(true);
		progressbar.setBackground(Color.pink);
		container.add(progressbar);

		JTextArea textArea = new JTextArea(200, 420);
		textArea.setForeground(Color.BLUE);
		textArea.setBackground(Color.lightGray);
		textArea.setPreferredSize(new Dimension(420,200));
		JScrollPane scrollableTextArea = new JScrollPane(textArea);
		scrollableTextArea.setBounds(20,160,420,200);
		scrollableTextArea.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
		scrollableTextArea.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
		container.add(scrollableTextArea);

		start = new JButton("开始发送");
		start.setBounds(285,65,100,25);
		container.add(start);
		cancel = new JButton("取消");
		cancel.setBounds(190,110,80,25);
		cancel.addActionListener(new CancelActionListener());
		container.add(cancel);
		JButton pause = new JButton("暂停");
		pause.setBounds(50,110,80,25);
		container.add(pause);
		frame.setDefaultCloseOperation(
				JFrame.EXIT_ON_CLOSE);
		frame.setResizable(false);
		frame.setVisible(true);
		pause.addActionListener(new PauseActionListener(null,pause));
		start.addActionListener((ActionEvent e) -> {
			if (socket.isClosed()){
				createSocket(ip);
				progressbar.setValue(0);
				cancel.setText("取消");
			}
			JFileChooser fc = null;
			if (path != null){
				fc = new JFileChooser(path);
			}else {
				String property = System.getProperty("user.dir");
				fc = new JFileChooser(property.substring(0,property.indexOf("\\")+1));
			}
			int status = fc.showOpenDialog(null);
			if (status == JFileChooser.APPROVE_OPTION) {
				path = fc.getSelectedFile().getPath();
				textArea.append(path);
				textArea.append("\n");
				threadPoolExecutor.execute(new SendTask());
			}
		});
	}

	class SendTask implements Runnable {
		@Override
		public void run() {
			try (DataOutputStream dos = new DataOutputStream(new BufferedOutputStream(socket.getOutputStream()));
				 DataInputStream dis = new DataInputStream(new BufferedInputStream(socket.getInputStream()));
				 RandomAccessFile rad = new RandomAccessFile(path, "r")) {
				start.setEnabled(false);
				File file = new File(path);
				dos.writeUTF("ok");
				dos.flush();
				dos.writeUTF(file.getName());
				dos.flush();
				String rsp = dis.readUTF();
				if (rsp.equals("ok")) {
					long size = dis.readLong();//读取文件已发送的大小
					long allSize = rad.length();
					dos.writeLong(allSize);
					dos.flush();
					dos.writeUTF("ok");
					dos.flush();
					offset = size;
					int barSize = (int) (allSize / 1048576);
					barOffset = (int) (size / 1048576);
					progressbar.setMaximum(barSize == 0? 1:barSize);
					progressbar.setValue(barOffset);
				}
				label.setText(file.getName() + " 发送中");
				//从文件指定位置开始传输
				byte[] buf = new byte[1048576];
				if (offset < rad.length()) {
					rad.seek(offset);
					long allLength = 0;
					long length = 0;
					setTime();
					while ((length = rad.read(buf)) != -1) {
						if (resume) {
							allLength +=length;
							dos.write(buf, 0, (int)length);
							progressbar.setValue(++barOffset);
						}else {
							synchronized (lock){
								synchronized (lock2) {
									rad.seek(rad.getFilePointer() - length);
									allLength = allLength - length;
									Threads.wait(lock,1000);
								}
							}
						}
					}
					System.out.println("send:"+Thread.currentThread().getName());
					System.out.println("allLength:"+allLength);
					dos.flush();
					timer.cancel();

				}
				cancel.setText("完成");
				start.setEnabled(true);
				label.setText(file.getName() + " 发送完成");
			} catch (IOException e1) {
				label.setText("对方取消接收,连接关闭!");
				e1.printStackTrace();
				timer.cancel();
				Threads.shutdownAndAwaitTermination(threadPoolExecutor);
				//logger.error(":", e1);

			}
		}
	}
	private void setTime(){
		TimerTask task = new TimerTask(){
			@Override
			public void run() {
				if (resume) {
					counter++;
					int minute = counter / 60;
					int second = counter % 60;
					time.setText("耗时:"+minute+"分"+second+"秒");
				}else {
					synchronized (lock){
						Threads.wait(lock);
					}
				}
			}};
		//计时器
		timer = new Timer();
		timer.schedule(task,0,1000);
	}
	class PauseActionListener implements ActionListener{
		JButton pause;
		final SendTask sendTask;
		public PauseActionListener(SendTask sendTask,JButton pause){
			this.pause = pause;
			this.sendTask = sendTask;
		}
		@Override
		public void actionPerformed(ActionEvent e) {
			JButton source = (JButton)e.getSource();
			if ("暂停".equals(source.getText())){
				pause.setText("继续");
				resume = false;
				return;
			}
			if ("继续".equals(source.getText())){
				pause.setText("暂停");
				resume = true;
				synchronized (lock){
					lock.notifyAll();

				}
				synchronized (lock2){
					lock2.notify();
				}
			}
		}
	}
	class CancelActionListener implements ActionListener {
		@Override
		public void actionPerformed(ActionEvent e3) {
			try {
				//dos.flush();
				JButton source = (JButton)e3.getSource();
				String message = "已取消接收，连接关闭！";
				String text = source.getText();
				if ("完成".equals(text)){
					message = "完成接收,连接即将关闭";
				}
				JOptionPane.showMessageDialog(frame, message, "提示：", JOptionPane.INFORMATION_MESSAGE);
				socket.close();
				frame.dispose();
				timer.cancel();
				Threads.shutdownAndAwaitTermination(threadPoolExecutor);
				System.exit(0);
			} catch (IOException e1) {
				//logger.error("::",e1);
				e1.printStackTrace();
			}
		}
	}



	public static void main(String[] args) {
		JFrame frame = new JFrame("文件传送窗口");
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.setResizable(false);
		frame.setSize(524, 285);
		//frame.setLocation(2809, 533);
		JLabel label = new JLabel("选择你的操作");
		label.setBounds(100,20,400,30);
		JRadioButton rb1,rb2;
		JButton button;
		rb1 = new JRadioButton("接收文件:");
		rb1.setSelected(true);
		rb1.setBounds(100,50,100,30);
		rb2 = new JRadioButton("发送文件:");
		rb2.setBounds(100,100,100,30);
		ButtonGroup buttonGroup = new ButtonGroup();
		buttonGroup.add(rb1);
		buttonGroup.add(rb2);
		button = new JButton("确定");
		button.setBounds(100,150,80,30);
		frame.add(label);
		frame.add(rb1);
		frame.add(rb2);
		frame.add(button);
		frame.setLayout(null);
		frame.setVisible(true);
		button.addActionListener(new ButtonActionListener(frame,rb1,rb2));
	}
	static class ButtonActionListener implements ActionListener{
		final Object  lock = new Object();
		final Object lock2 = new Object();
		private JRadioButton rb1,rb2;
		private JFrame frame;
		public ButtonActionListener(JFrame frame,JRadioButton button, JRadioButton button2) {
			this.frame = frame;
			this.rb1 = button;
			this.rb2 = button2;
		}

		@Override
		public void actionPerformed(ActionEvent e) {
			if(rb1.isSelected()){
				int dialog = JOptionPane.showConfirmDialog(frame, "接收文件?","选择",JOptionPane.YES_NO_OPTION);
				if (dialog == JOptionPane.OK_OPTION){
					frame.dispose();
					new ReceiveFileThread(lock2,Threads.threadPoolExecutor()).start();
				}
			}
			if(rb2.isSelected()){
				int dialog = JOptionPane.showConfirmDialog(frame, "发送文件?","选择",JOptionPane.YES_NO_OPTION);
				if (dialog == JOptionPane.OK_OPTION){
					frame.dispose();
					JFrame jFrame  = new JFrame("填写ip");
					jFrame.setSize(490, 200);
					jFrame.setResizable(false);
					jFrame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
					//jFrame.setLocation(2809, 533);
					JPanel panel = new JPanel();
					panel.setLayout(null);
					JLabel ipLabel = new JLabel("输入对方ip:");
					ipLabel.setFont(new Font("微软雅黑",Font.BOLD,15));
					ipLabel.setBounds(50,70,80,30);
					panel.add(ipLabel);
					JTextField userText = new JTextField(17);
					userText.setText("127.0.0.1");
					userText.setBounds(135,70,165,30);
					panel.add(userText);
					JButton sure = new JButton("确定");
					sure.setBounds(290,70,80,30);
					panel.add(sure);
					jFrame.add(panel);
					jFrame.setVisible(true);
					jFrame.setLayout(null);
					final String[] text = {""};
					sure.addActionListener((ActionEvent e2)->{
						text[0] = userText.getText();
						if ("".equals(text[0])){
							JOptionPane.showConfirmDialog(jFrame,"输入对方ip","提示", JOptionPane.OK_CANCEL_OPTION);
						}else {
							String reg = "^((2((5[0-5])|([0-4]\\d)))|([0-1]?\\d{1,2}))(\\.((2((5[0-5])|([0-4]\\d)))|([0-1]?\\d{1,2}))){3}$";
							if (!text[0].matches(reg)){
								JOptionPane.showMessageDialog(jFrame, "请输入正确ip!", "提示：", JOptionPane.WARNING_MESSAGE);
								return ;
							}
							try {
								boolean reachable = InetAddress.getByName(text[0]).isReachable(3000);
								if (!reachable){
									JOptionPane.showMessageDialog(jFrame, "ip地址连接不通,请确保在相同局域网内!", "提示：", JOptionPane.WARNING_MESSAGE);
									return;
								}
							} catch (IOException ex) {
								JOptionPane.showMessageDialog(jFrame, ex.getMessage(), "提示：", JOptionPane.WARNING_MESSAGE);
								return;
							}
							jFrame.dispose();
							new ReceiveFileThread(lock2,Threads.threadPoolExecutor()).start();
							Threads.sleep(3000);
							new SendFileThread(lock,lock2,text[0]).startSend();
						}
					});
				}
			}
		}
	}

}


